// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const { ccclass, property, executeInEditMode } = cc._decorator;

@ccclass
@executeInEditMode
export default class Ink extends cc.Component {
    @property
    private _range: number = 0;

    @property({
        step: 0.1,
        min: 0,
        max: 1,
        slide: true
    })
    get range(): number {
        return this._range;
    }

    set range(value: number) {
        this._range = value;
        this.updateRange();
    }

    @property
    private _borderSmooth: number = 10;

    @property({
        min: 0
    })
    get borderSmooth(): number {
        return this._borderSmooth;
    }
    set borderSmooth(value: number) {
        this._borderSmooth = value;
        this.updateBorderSmooth();
    }

    private _center: cc.Vec2 = cc.v2(0.5, 0.5);

    @property({
        min: 0
    })
    time: number = 0.3;

    @property
    minScale: number = 0.5;

    @property
    maxScale: number = 1;

    private _mat: cc.Material = null;
    private _maskRadius: number = 0;

    protected onLoad(): void {
        this._mat = this.node.getComponent(cc.Sprite).getMaterial(0);
        this.updateBorderSmooth();
        this.updateCenterPos();
        this.play();
    }

    protected onEnable(): void {
        this.node.on(cc.Node.EventType.SCALE_CHANGED, this.updateCenterPos, this);
    }

    protected onDisable(): void {
        this.node.off(cc.Node.EventType.SCALE_CHANGED, this.updateCenterPos, this);
    }

    public play() {
        cc.tween(this).set({ range: 0 }).to(this.time, { range: 1 }, { easing: "cubicOut" }).start();
    }

    private updateCenterPos() {
        let worldBox = this.node.getBoundingBoxToWorld();
        let box = cc.v2(worldBox.width, worldBox.height);
        let centerPos = cc.v2(this._center.x, this._center.y).multiply(box);
        let pos = worldBox.origin.add(centerPos);
        this._mat && this._mat.setProperty("u_centerPos", pos);

        this.updateMaskRadius();
        this.updateRange();
    }

    private updateRange() {
        this._mat && this._mat.setProperty("u_range", this._range * this._maskRadius);
    }

    private updateBorderSmooth() {
        this._mat && this._mat.setProperty("u_borderSmoot", this._borderSmooth);
    }

    private updateMaskRadius() {
        let worldBox = this.node.getBoundingBoxToWorld();
        let box = cc.v2(worldBox.width, worldBox.height);
        let topLeftRadius = cc.v2(0, 1).subSelf(this._center).multiply(box).len();
        let topRightRadius = cc.v2(1, 1).subSelf(this._center).multiply(box).len();
        let bottomLeftRadius = cc.v2(0, 0).subSelf(this._center).multiply(box).len();
        let bottomRightRadius = cc.v2(1, 0).subSelf(this._center).multiply(box).len();
        this._maskRadius = Math.max(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    }
}
